<!doctype html>
<html>

<head>
<title>Grant, Rollins, Burgess &raquo; COS 452 &mdash; Assignment 3</title> 
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">

<script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
<script type="text/javascript" src="webgl-utils.js"></script>

<script id="shader-fs" type="x-shader/x-fragment">
        #ifdef GL_ES
        precision highp float;
        #endif

        varying vec4 vColor;
        void main(void) {
                gl_FragColor = vColor;
        }
</script>

<script id="shader-vs" type="x-shader/x-vertex">
        attribute vec3 aVertexPosition;
        attribute vec4 aVertexColor;
 
        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;
 
        varying vec4 vColor;
        void main(void) {
                gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
                vColor = aVertexColor;
        }
</script>


<script type="text/javascript">
        var gl;

        function initGL(canvas) {
                try {
                        gl = canvas.getContext("experimental-webgl");
                        gl.viewportWidth = canvas.width;
                        gl.viewportHeight = canvas.height;
                } catch (e) {}
                if (!gl) 
                        alert("Could not initialise WebGL, sorry :-(");
        }

        function getShader(gl, id) {
                var shaderScript = document.getElementById(id);
                if (!shaderScript)
                        return null;

                var str = "";
                var k = shaderScript.firstChild;
                while (k) {
                        if (k.nodeType == 3)
                                str += k.textContent;
                        k = k.nextSibling;
                } // while

                var shader;
                if (shaderScript.type == "x-shader/x-fragment") {
                        shader = gl.createShader(gl.FRAGMENT_SHADER);
                } else if (shaderScript.type == "x-shader/x-vertex") {
                        shader = gl.createShader(gl.VERTEX_SHADER);
                } else {
                        return null;
                }

                gl.shaderSource(shader, str);
                gl.compileShader(shader);

                if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                        alert(gl.getShaderInfoLog(shader));
                        return null;
                }

                return shader;
        }

        var shaderProgram;

        function initShaders() {
                var fragmentShader = getShader(gl, "shader-fs");
                var vertexShader = getShader(gl, "shader-vs");

                shaderProgram = gl.createProgram();
                gl.attachShader(shaderProgram, vertexShader);
                gl.attachShader(shaderProgram, fragmentShader);
                gl.linkProgram(shaderProgram);

                if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
                        alert("Could not initialise shaders");
                }

                gl.useProgram(shaderProgram);

                shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
                gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
 
                shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
                gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
	
                shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
                shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
        }

        var mvMatrix = mat4.create();
        var mvMatrixStack = [];
        var pMatrix = mat4.create();

        function mvMatrixPush() {
                var copy = mat4.create();
                mat4.set(mvMatrix, copy);
                mvMatrixStack.push(copy);
        }

        function mvMatrixPop() {
                if (mvMatrixStack.length == 0) 
                        throw "Invalid popMatrix!";
                mvMatrix = mvMatrixStack.pop();
        }
    
        function setMatrixUniforms() {
                gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
                gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
        }

        function degToRad(degrees) {
                return degrees * Math.PI / 180;
        }

	var currentlyPressedKeys = {};

	function handleKeyDown(event) {
        	currentlyPressedKeys[event.keyCode] = true;
	}

	function handleKeyUp(event) {
		currentlyPressedKeys[event.keyCode] = false;
	}

	var pitch = 0;
	var pitchRate = 0;

	var yaw = 0;
	var yawRate = 0;

	var xPos = 0;
	var yPos = 0.4;
	var zPos = 0;

	var speed = 0;
	
	var perspectiveView = 1;
	
	var echo = 0;

	function handleKeys() {
		
		// debug echo 
		echo = 0;
		if (currentlyPressedKeys[69]) {
			echo = 1;
		}
		
		// view type
		if (currentlyPressedKeys[79]) {
			perspectiveView = 0;
		} else if (currentlyPressedKeys[80]) {
			perspectiveView = 1;
		}
		
		// look up down
		if (currentlyPressedKeys[33]) {
			// Page Up
			pitchRate = 0.1;
		} else if (currentlyPressedKeys[34]) {
			// Page Down
			pitchRate = -0.1;
		} else {
			pitchRate = 0;
		}

		// look left right
		if (currentlyPressedKeys[37] || currentlyPressedKeys[65]) {
			// Left cursor key
			yawRate = 0.1;
		} else if (currentlyPressedKeys[39] || currentlyPressedKeys[68]) {
			// Right cursor key
			yawRate = -0.1;
		} else {
			yawRate = 0;
		}

		// move forward/backward
		if (currentlyPressedKeys[38] || currentlyPressedKeys[87]) {
			// Up cursor key
			speed = 0.003;
		} else if (currentlyPressedKeys[40] || currentlyPressedKeys[83]) {
			// Down cursor key
			speed = -0.003;
		} else {
			speed = 0;
		}
	}


	var roomVertexPositionBuffer = null;
	var roomVertexColorBuffer = null;
	var roomVertexPositionBoundary;
	
	function handleRoom(data) {
		roomVertexPositionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, roomVertexPositionBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.room.vertexPositions), gl.STATIC_DRAW);
		roomVertexPositionBuffer.itemSize = data.room.positionItemSize;
		roomVertexPositionBuffer.numItems = data.room.positionNumItems;
		
		roomVertexPositionBoundary = data.room.positionBoundary;
		
		roomVertexColorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, roomVertexColorBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.room.vertexColors), gl.STATIC_DRAW);
		roomVertexColorBuffer.itemSize = data.room.colorItemSize;
		roomVertexColorBuffer.numItems = data.room.colorNumItems;
	}

	// eric's model buffers
	var ericCubePositionBuffer = null;
	var ericCubeColorBuffer = null;
	var ericCubeVertexIndexBuffer = null;
	var ericSconcePositionBuffer = null;
	var ericSconceColorBuffer = null;
	var ericSconceVertexIndexBuffer  = null;
	function handleEricsModels(data) {
	
		// setup ericCubePositionBuffer		
		ericCubePositionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, ericCubePositionBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.eric.pyramid.vertexPositions), gl.STATIC_DRAW);
		ericCubePositionBuffer.itemSize = data.eric.pyramid.positionItemSize;
		ericCubePositionBuffer.numItems = data.eric.pyramid.positionNumItems;
		
		// setup ericCubeColorBuffer
		ericCubeColorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, ericCubeColorBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.eric.pyramid.vertexColors), gl.STATIC_DRAW);
		ericCubeColorBuffer.itemSize = data.eric.pyramid.colorItemSize;
		ericCubeColorBuffer.numItems = data.eric.pyramid.colorNumItems;
		
		// setup ericCubeVertexIndexBuffer
		ericCubeVertexIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ericCubeVertexIndexBuffer);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data.eric.pyramid.vertexIndicies), gl.STATIC_DRAW);
                ericCubeVertexIndexBuffer.itemSize = data.eric.pyramid.indexItemSize;
                ericCubeVertexIndexBuffer.numItems = data.eric.pyramid.indexNumItems;
		
		// setup ericSconcePositionBuffer
		ericSconcePositionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, ericSconcePositionBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.eric.sconce.vertexPositions), gl.STATIC_DRAW);
		ericSconcePositionBuffer.itemSize = data.eric.sconce.positionItemSize;
		ericSconcePositionBuffer.numItems = data.eric.sconce.positionNumItems;
		
		// setup ericSconceColorBuffer
		ericSconceColorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, ericSconceColorBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.eric.sconce.vertexColors), gl.STATIC_DRAW);
		ericSconceColorBuffer.itemSize = data.eric.sconce.colorItemSize;
		ericSconceColorBuffer.numItems = data.eric.sconce.colorNumItems;
		
		// setup ericSconceVertexIndexBuffer
		ericSconceVertexIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ericSconceVertexIndexBuffer);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data.eric.sconce.vertexIndicies), gl.STATIC_DRAW);
                ericSconceVertexIndexBuffer.itemSize = data.eric.sconce.indexItemSize;
                ericSconceVertexIndexBuffer.numItems = data.eric.sconce.indexNumItems;
	}
	
	function handleEricasModels(data) {
	}
	
	// alex's model buffers
	var alexCubePositionBuffer = null;
	var alexCubeColorBuffer = null;
	var alexCubeVertexIndexBuffer = null;
	var alexSconcePositionBuffer = null;
	var alexSconceColorBuffer = null;
	var alexSconceVertexIndexBuffer  = null;
	
	function handleAlexsModels(data) {		
		
		// setup alexCubePositionBuffer		
		alexCubePositionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, alexCubePositionBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.alex.cube.vertexPositions), gl.STATIC_DRAW);
		alexCubePositionBuffer.itemSize = data.alex.cube.positionItemSize;
		alexCubePositionBuffer.numItems = data.alex.cube.positionNumItems;
		
		// setup alexCubeColorBuffer
		alexCubeColorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, alexCubeColorBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.alex.cube.vertexColors), gl.STATIC_DRAW);
		alexCubeColorBuffer.itemSize = data.alex.cube.colorItemSize;
		alexCubeColorBuffer.numItems = data.alex.cube.colorNumItems;
		
		// setup alexCubeVertexIndexBuffer
		alexCubeVertexIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, alexCubeVertexIndexBuffer);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data.alex.cube.vertexIndicies), gl.STATIC_DRAW);
                alexCubeVertexIndexBuffer.itemSize = data.alex.cube.indexItemSize;
                alexCubeVertexIndexBuffer.numItems = data.alex.cube.indexNumItems;
		
		// setup alexSconcePositionBuffer
		alexSconcePositionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, alexSconcePositionBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.alex.sconce.vertexPositions), gl.STATIC_DRAW);
		alexSconcePositionBuffer.itemSize = data.alex.sconce.positionItemSize;
		alexSconcePositionBuffer.numItems = data.alex.sconce.positionNumItems;
		
		// setup alexSconceColorBuffer
		alexSconceColorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, alexSconceColorBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data.alex.sconce.vertexColors), gl.STATIC_DRAW);
		alexSconceColorBuffer.itemSize = data.alex.sconce.colorItemSize;
		alexSconceColorBuffer.numItems = data.alex.sconce.colorNumItems;
		
		// setup alexSconceVertexIndexBuffer
		alexSconceVertexIndexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, alexSconceVertexIndexBuffer);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data.alex.sconce.vertexIndicies), gl.STATIC_DRAW);
                alexSconceVertexIndexBuffer.itemSize = data.alex.sconce.indexItemSize;
                alexSconceVertexIndexBuffer.numItems = data.alex.sconce.indexNumItems;
	}
	
	function loadWorld() {
		var request = new XMLHttpRequest();
		request.open("GET", "world.json");
		request.onreadystatechange = function () {
			if (request.readyState == 4) {
				data = JSON.parse(request.responseText);
				handleRoom(data);
				handleEricsModels(data);
				handleEricasModels(data);
				handleAlexsModels(data);
				document.getElementById("loadingtext").textContent = "";
			}
		}
		request.send();
	}

	function drawRoom() {
		mvMatrixPush();
		
		// setup the mvMatrix
		mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]);
		mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]);
		mat4.translate(mvMatrix, [-xPos, -yPos, -zPos]);
		
		// assign vertex and colors to the attributes in the program
		gl.bindBuffer(gl.ARRAY_BUFFER, roomVertexColorBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, roomVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
		gl.bindBuffer(gl.ARRAY_BUFFER, roomVertexPositionBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, roomVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

		// commit mvMatrix and pMatrix to uniforms in the program
		setMatrixUniforms();
		
		// draw triangles using vertices
		gl.drawArrays(gl.TRIANGLES, 0, roomVertexPositionBuffer.numItems);
		
		mvMatrixPop();
	}
	
		function drawEric() {
	
		mvMatrixPush();		
		/*** START CUBE ***/
		// setup the mvMatrix
		// fixed cube for now in 3rd quadrant on floor
		mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]);
		mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]);
		mat4.translate(mvMatrix, [-xPos+movement, -yPos, -zPos-2.0+chaseMovement]);
		mat4.scale(mvMatrix, [0.25,0.25,0.25]);
		mat4.rotate(mvMatrix, degToRad(-90), [1, 0, 0]);
		
		// assign vertex position, colors to the attributes in the program		
		gl.bindBuffer(gl.ARRAY_BUFFER, ericCubeColorBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, ericCubeColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
		gl.bindBuffer(gl.ARRAY_BUFFER, ericCubePositionBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, ericCubePositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
		// assign indicies
		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ericCubeVertexIndexBuffer);

		// commit mvMatrix and pMatrix to uniforms in the program
		setMatrixUniforms();
		
		// draw cube using indicies
		gl.drawElements(gl.TRIANGLES, ericCubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
		/*** END CUBE ***/
		mvMatrixPop();
		
		mvMatrixPush();
		/*** START SCONCE ***/
		// setup the mvMatrix
		// fixed sconce for now in 3rd quadrant on wall
		mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]);
		mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]);
		mat4.translate(mvMatrix, [-xPos+2, -yPos+.7, -zPos-2]);
		mat4.scale(mvMatrix, [0.25,0.25,0.25]);
		
		// assign vertex position, colors to the attributes in the program		
		gl.bindBuffer(gl.ARRAY_BUFFER, ericSconceColorBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, ericSconceColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
		gl.bindBuffer(gl.ARRAY_BUFFER, ericSconcePositionBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, ericSconcePositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
		// assign indicies
		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ericSconceVertexIndexBuffer);

		// commit mvMatrix and pMatrix to uniforms in the program
		setMatrixUniforms();
		
		// draw sconce using indicies
		gl.drawElements(gl.TRIANGLES, ericSconceVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
		/*** END SCONCE ***/		
		mvMatrixPop();
	}
	
	function drawAlex() {
	
		mvMatrixPush();		
		/*** START CUBE ***/
		// setup the mvMatrix
		// fixed cube for now in 3rd quadrant on floor
		mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]);
		mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]);
		mat4.translate(mvMatrix, [-xPos-2.0, -yPos+.2, -zPos-2.0]);
		
		// assign vertex position, colors to the attributes in the program		
		gl.bindBuffer(gl.ARRAY_BUFFER, alexCubeColorBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, alexCubeColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
		gl.bindBuffer(gl.ARRAY_BUFFER, alexCubePositionBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, alexCubePositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
		// assign indicies
		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, alexCubeVertexIndexBuffer);

		// commit mvMatrix and pMatrix to uniforms in the program
		setMatrixUniforms();
		
		// draw cube using indicies
		gl.drawElements(gl.TRIANGLES, alexCubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
		/*** END CUBE ***/
		mvMatrixPop();
		
		mvMatrixPush();
		/*** START SCONCE ***/
		// setup the mvMatrix
		// fixed sconce for now in 3rd quadrant on wall
		mat4.rotate(mvMatrix, degToRad(-pitch), [1, 0, 0]);
		mat4.rotate(mvMatrix, degToRad(-yaw), [0, 1, 0]);
		mat4.translate(mvMatrix, [-xPos-2.75, -yPos+.7, -zPos-3.0]);
		
		// assign vertex position, colors to the attributes in the program		
		gl.bindBuffer(gl.ARRAY_BUFFER, alexSconceColorBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, alexSconceColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
		gl.bindBuffer(gl.ARRAY_BUFFER, alexSconcePositionBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, alexSconcePositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
		// assign indicies
		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, alexSconceVertexIndexBuffer);

		// commit mvMatrix and pMatrix to uniforms in the program
		setMatrixUniforms();
		
		// draw sconce using indicies
		gl.drawElements(gl.TRIANGLES, alexSconceVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
		/*** END SCONCE ***/		
		mvMatrixPop();
	}
	
	function drawScene() {
		gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

		// if we've been called before the world is loaded...
		if (roomVertexColorBuffer == null || roomVertexPositionBuffer == null)
			return;

		if (perspectiveView == 1) {
			mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
			document.getElementById("viewType").textContent = "Perspective";
		}
		else {
			mat4.ortho(-1, 1, -1, 1, 0.1, 100.0, pMatrix);
			document.getElementById("viewType").textContent = "Orthogonal";
		}

		mat4.identity(mvMatrix);
		
		drawRoom();
		
		drawAlex();
		drawEric();
	}


	var lastTime = 0;
	// Used to make us "jog" up and down as we move forward.
	var joggingAngle = 0;

	var movement = 0;
	var increasing = true;
	var chase = false;
	var chaseMovement = 0;
	var chaseIncreasing = true;
	var counter = 0;
	function animate() {
		var timeNow = new Date().getTime();
		if (lastTime != 0) {
			var elapsed = timeNow - lastTime;
			if(!chase){
				if(increasing && movement<1){
					movement = movement + 0.01;
				}
				else if(increasing && movement>=1){
					increasing = false;
				}
				
				else if(!increasing && movement>-1){
					movement = movement - 0.01;
				}
				else{
					increasing = true;
				}
				if(movement>=-0.01 && movement<=0.01){
					counter++;
				}
				if(counter>=5){
					chase = true;
					counter = 0;
					movement = 0
				}
			}
			else{
				if(chaseMovement<1 && chaseIncreasing){
					chaseMovement = chaseMovement + 0.01;
				}
				else if(chase>=1 && chaseIncreasing){
					chaseIncreasing = false;
				}
				
				else if(chaseMovement>0 && !chaseIncreasing){
					chaseMovement = chaseMovement - 0.01;
				}
				else{
					chaseIncreasing = true;
				}
				
				if(chaseMovement>=0 && chaseMovement<=0.015){
					counter++;
				}
				if(counter>=5){
					chase = false;
					counter = 0;
					chaseMovement = 0
				}
			}

			if (speed != 0) {
				var xProposed = xPos - Math.sin(degToRad(yaw)) * speed * elapsed;
				var zProposed = zPos - Math.cos(degToRad(yaw)) * speed * elapsed;
				
				// check the boundaries
				if (Math.abs(xProposed) <= roomVertexPositionBoundary)
					xPos = xProposed;
				if (Math.abs(zProposed) <= roomVertexPositionBoundary)
					zPos = zProposed;
				
				// bouncy y for 'walking'
				joggingAngle += elapsed * 0.6; 
				yPos = Math.sin(degToRad(joggingAngle)) / 20 + 0.4
			}

			yaw += yawRate * elapsed;
			pitch += pitchRate * elapsed;
			
		}
		lastTime = timeNow;
	}

	function tick() {
		requestAnimFrame(tick);
		handleKeys();
		drawScene();
		animate();
	}

	function debug(string) {
		document.getElementById("echoOutput").textContent = string;
	}

	
	function webGLStart() {
		var canvas = document.getElementById("assignment3-canvas");
		initGL(canvas);
		initShaders();
		loadWorld();

		gl.clearColor(0.0, 0.0, 0.0, 1.0);
		gl.enable(gl.DEPTH_TEST);

		document.onkeydown = handleKeyDown;
		document.onkeyup = handleKeyUp;
		
		tick();
	}

</script>
</head>
<body onload="webGLStart();">

	<div>
		<span id="loadingtext">world loading...</span>
	</div>

	<div>
		<canvas id="assignment3-canvas" style="border: none;" width="500" height="500"></canvas>
	</div>
	<div>
		<span id="viewType"></span>
	</div>

	<h2>Controls:</h2>
	<ul>		
                <li><span>Arrow keys Up/Down or 'w'/'s' <strong>move</strong> Forward, Backward</span></li>
		<li><span>Arrow keys Left/Right or 'a'/'d' <strong>rotate</strong> Left, Right</span></li>
                <li><span>Page Up/Down <strong>look</strong> Up, Down</span></li>
		<li><span>'o' <strong>Orthogonal</strong> view projection</span></li>
		<li><span>'p' <strong>Perspective</strong> view projection (default)</span></li>
	</ul>
	
<!--
	<h2>Debug:</h2>
	<ul>
		<li><span>'e' <strong>Echo</strong> conditional debug string; usage: if (echo) debug(string);</span></li>
	</ul>
	<div><span id="echoOutput">no debug output</span></div>
-->
</body>

</html>
